﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Extention.ENode.Rpc.Runtime.Communally.Entitys.Address;
using Extention.ENode.Rpc.Runtime.Communally.Serialization;

namespace Extention.ENode.Rpc.Routing.Impl
{
    /// <summary>
    /// 服务路由变更事件参数
    /// </summary>
    public class ServiceRouteChangedEventArgs : ServiceRouteEventArgs
    {
        public ServiceRouteChangedEventArgs(ServiceRoute route, ServiceRoute oldRoute) : base(route)
        {
            OldRoute = oldRoute;
        }

        /// <summary>
        /// 旧的服务路由信息
        /// </summary>
        public ServiceRoute OldRoute { get; set; }
    }

    /// <summary>
    /// 服务路由管理者基类
    /// </summary>
    public abstract class ServiceRouteManagerBase : IServiceRouteManager
    {
        private readonly ISerializer<string> _serializer;
        private EventHandler<ServiceRouteEventArgs> _created;
        private EventHandler<ServiceRouteEventArgs> _removed;
        private EventHandler<ServiceRouteChangedEventArgs> _changed;

        protected ServiceRouteManagerBase(ISerializer<string> serializer)
        {
            _serializer = serializer;
        }

        /// <summary>
        /// 服务路由被创建
        /// </summary>
        public event EventHandler<ServiceRouteEventArgs> Created
        {
            add { _created += value; }
            remove { _created -= value; }
        }

        /// <summary>
        /// 服务路由被删除
        /// </summary>
        public event EventHandler<ServiceRouteEventArgs> Removed
        {
            add { _removed += value; }
            remove { _removed -= value; }
        }

        /// <summary>
        /// 服务路由被修改
        /// </summary>
        public event EventHandler<ServiceRouteChangedEventArgs> Changed
        {
            add { _changed += value; }
            remove { _changed -= value; }
        }

        /// <summary>
        /// 获取所有可用的服务路由信息
        /// </summary>
        /// <returns>服务路由集合</returns>
        public abstract Task<IEnumerable<ServiceRoute>> GetRoutesAsync();

        /// <summary>
        /// 获取所有服务的key
        /// </summary>
        /// <returns></returns>
        public abstract Task<List<string>> GetServerKey();

        /// <summary>
        /// 获取单条可用路由
        /// </summary>
        /// <param name="serviceId"></param>
        /// <returns></returns>
        public abstract Task<ServiceRoute> GetRouteAsync(string serviceId);
        /// <summary>
        /// 获取负载信息
        /// </summary>
        /// <param name="serverName"></param>
        /// <returns></returns>
        public abstract Task<IEnumerable<IpAddressModel>> GetBalanceAsync(string serverName);

        /// <summary>
        /// 设置服务路由
        /// </summary>
        /// <param name="routes">服务路由集合</param>
        /// <param name="serviceInfo">rpc服务的名称</param>
        /// <returns>一个任务</returns>
        Task IServiceRouteManager.SetRoutesAsync(IEnumerable<ServiceRoute> routes, IpAddressModel serviceInfo)
        {
            if (routes == null)
                throw new ArgumentNullException(nameof(routes));
            foreach (var item in routes)
            {
                item.ServiceDescriptor.BusServiceName = serviceInfo.ServiceName;
            }
            var descriptors = routes.Where(route => route != null).Select(route => new ServiceRouteDescriptor
            {
                ServiceDescriptor = route.ServiceDescriptor,
            });
            return SetRoutesAsync(descriptors, serviceInfo);
        }

        /// <summary>
        /// 清空所有的服务路由
        /// </summary>
        /// <returns>一个任务</returns>
        public abstract Task ClearAsync(IpAddressModel serverInfo);

        /// <summary>
        /// 设置服务路由
        /// </summary>
        /// <param name="routes">服务路由集合</param>
        /// <param name="serviceInfo">服务信息</param>
        /// <returns>一个任务</returns>
        protected abstract Task SetRoutesAsync(IEnumerable<ServiceRouteDescriptor> routes, IpAddressModel serviceInfo);

        /// <summary>
        /// 设置负载信息
        /// </summary>
        /// <param name="serverInfo"></param>
        /// <returns></returns>
        public abstract Task SetBalanceAsync(IpAddressModel serverInfo);
        protected void OnCreated(params ServiceRouteEventArgs[] args)
        {
            if (_created == null)
                return;

            foreach (var arg in args)
                _created(this, arg);
        }

        protected void OnChanged(params ServiceRouteChangedEventArgs[] args)
        {
            if (_changed == null)
                return;

            foreach (var arg in args)
                _changed(this, arg);
        }

        protected void OnRemoved(params ServiceRouteEventArgs[] args)
        {
            if (_removed == null)
                return;

            foreach (var arg in args)
                _removed(this, arg);
        }
    }
}